using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Xml.Serialization;
using Microsoft.SharePoint;

namespace PS.WebParts.Rollup.GridViewWebPart
{
    public class DynamicColumn 
        : FormattedColumn
    {
        private Dictionary<string, Converter<object, string>> extendedProperties;

        private SPSite site;

        [XmlIgnore]
        public SPSite Site
        {
            set { site = value; }
            get
            {
                if (null == site)
                {
                    return SPContext.Current.Site;
                }
                return site;
            }
        }

        private string GetItemUrl(object container, PAGETYPE pageType)
        {
            using (SPWeb web = Site.OpenWeb(new Guid(DataBinder.GetPropertyValue(container, "_WebId").ToString())))
            {
                string url = web.Lists[new Guid(DataBinder.GetPropertyValue(container, "_ListId").ToString())].Forms[pageType].Url;

                string serverRelativeUrl = Site.ServerRelativeUrl;
                if (!serverRelativeUrl.EndsWith("/"))
                {
                    serverRelativeUrl = serverRelativeUrl + "/";
                }

                return String.Format("{0}{1}?ID={2}", serverRelativeUrl, url, DataBinder.GetPropertyValue(container, "_ItemId"));
            }
        }

        private string GetEditUrl(object container)
        {
            return GetItemUrl(container, PAGETYPE.PAGE_EDITFORM);
        }

        private string GetDisplayUrl(object container)
        {
            return GetItemUrl(container, PAGETYPE.PAGE_DISPLAYFORM);
        }
        
        public DynamicColumn()
        {
            extendedProperties = new Dictionary<string,Converter<object,string>>();
            extendedProperties.Add("EditUrl", GetEditUrl);
            extendedProperties.Add("DisplayUrl", GetDisplayUrl);
        }

        internal override string GetFormatedString(object container)
        {
            StringBuilder result = new StringBuilder();
            char[] delemiters = new char[2] { '{', '}' };

            int current = 0;
            int lastTokenIndex = 0;
            int first = -1;
            int end = -1;
            for (; ; )
            {
                current = format.IndexOfAny(delemiters, current);
                if (-1 == current)
                {
                    result.Append(format.Substring(lastTokenIndex, format.Length - lastTokenIndex));
                    return result.ToString();
                }

                if ('{' == format[current])
                {
                    first = current;
                    current++;
                }
                if (-1 != first && '}' == format[current])
                {
                    end = current;
                    current++;
                }

                if (-1 != end)
                {
                    if (lastTokenIndex != first)
                    {
                        result.Append(format.Substring(lastTokenIndex, first - lastTokenIndex));
                    }

                    result.AppendFormat(GetProperty(container, format.Substring(first + 1, end - first - 1)));

                    lastTokenIndex = end + 1;

                    end = -1;
                    first = -1;
                }
            }
        }

        internal override string GetDisplayString(object container)
        {
            return string.Empty;
        }

        protected override DataControlField CreateField()
        {
            return new DateTimeColumn();
        }

        private string GetProperty(object container, string name)
        {
            Converter<object, string> method;

            if (extendedProperties.TryGetValue(name, out method))
            {
                return method(container);
            }
            else
            {
                return DataBinder.GetPropertyValue(container, name).ToString();
            }
        }
    }
}
